<?php

namespace App\Services\Sms;

use App\Constants\CodeData;
use App\Dao\UserDao;
use App\Exception\MessageException;
use App\Model\NoteSendRecord;
use App\Services\Sms\Aliyun\AliyunSms;
use App\Utils\FunUtil;
use App\Utils\LoggerUtil;
use App\Utils\MemcacheClient;
use function Hyperf\Config\config;

class SmsService
{
    public static $check_prex = 'phone_rand_'; //验证码标识前缀

    /**
     * Note - 发送短信验证码
     * DateTime 2024/8/20 17:29
     * User Admin
     * @param $params
     * @return array
     */
    public function captcha($params)
    {
        $uid = $params['uid'];
        $session_id = $params['session_id'];
        $phone = $params['phone'];
        $phone_country = $params['phone_country'] ?? '86';
        $type = $params['type'] ?? 1;// 1-表示绑定手机号码; 2-表示手机号码登录; 3-表示绑定银行信息

        if (config("envname") == 'dev' || config("envname") == 'audit' || in_array($phone, NOT_AUTH)) {
            return formatData(['result' => 1], 200, CodeData::NEED_TIPS, '发送成功');
        }

        $ip = FunUtil::getClientIp();

        if ($type == 1 || $type == 3) {
            FunUtil::checkUser($uid, $session_id);
        }

        $preg = '/^1[3456789]\d{9}$/';
        if ($phone_country == "86" && !preg_match($preg, $phone)) {
            return formatData('', 200, CodeData::NEED_TIPS, '抱歉，该号段暂不支持');
        }

        if ($type == 1) {
            $exist = UserDao::getInstance()->checkPhone($phone);
            if ($exist) return formatData('', 200, CodeData::NEED_TIPS, '手机号已被使用');
        }

        $instance = MemcacheClient::getInstance();
        //单个手机号1天10次现已由腾讯云控制
        if (!$instance->add("sms_phone_" . $phone, 1, 3600 * 24)) {
            $instance->increment("sms_phone_" . $phone, 1);
        }

        if ($instance->get("sms_phone_" . $phone) > 10) {
            return formatData('', 200, CodeData::NEED_TIPS, '您的操作太频繁了，先休息一下');
        }

        //	单ip1小时最多100次
        if (!$instance->add("sms_userIP_" . $ip, 1, 3600)) {
            $instance->increment("sms_userIP_" . $ip, 1);
        }

        if ($instance->get("sms_userIP_" . $ip) > 100) {
            return formatData('', 200, CodeData::NEED_TIPS, '您的操作太频繁了，先休息一下');
        }

        $phone_rand2 = $instance->get('phone_rand2_' . $phone);
        if (empty($phone_rand2)) {
            $phone_rand = mt_rand(100000, 999999);
            $instance->set(SmsService::$check_prex . $phone, $phone_rand, 600);    //1小时有效
            $instance->set('phone_rand2_' . $phone, $phone_rand, 60);    //60秒内不能重复发
        } else {
            LoggerUtil::write("sendsms", "phone_rand2_limit", "sendsms_request");
            return formatData('', 200, CodeData::NEED_TIPS, '60秒内不能重复发');
        }

        return $this->send($phone, $phone_rand, $uid, $type);
    }


    // 发送验证码
    public function send($phone, $phone_rand, $uid, $type): array
    {
        // send sms
        $signName = '寻缘';
        try {
            LoggerUtil::write('sendsms', ["phone" => $phone, "start"], 'sendsms_yunxin_result');
            // 阿里云验证码短信
            // 记录短信验证码
            $noteSendRecord = new NoteSendRecord();
            $noteId = $noteSendRecord->saveNote($uid, $phone, $phone_rand, $type);

            $res = AliyunSms::sendCode($phone, $phone_rand, $signName);
            LoggerUtil::write('sendsms', ["phone" => $phone, "result" => $res], 'aliyun_sms_result');

            if ($res['Code'] == 'OK') {
                $noteSendRecord->query()->where('id', $noteId)->update(["status" => "success"]);
                return formatData(['result' => 1], 200, CodeData::NEED_TIPS, '发送成功');
                // Tool::JSON(200, array('result' => 1), '发送成功');
            } else {
                $noteSendRecord->query()->where('id', $noteId)->update(["status" => "fail"]);
                return formatData(['result' => 1], 200, CodeData::NEED_TIPS, '发送失败');
                // Tool::JSON(200, array('result' => 1), '发送失败');
            }
        } catch (\Exception $e) {
            LoggerUtil::write('sendsms', ["err" => $e->getMessage(), "phone" => $phone], 'sendsms_aliyun_error');
        }
        return formatData(['result' => 1], 200, CodeData::NEED_TIPS, '发送失败');
    }


    // 验证短信
    public static function validateCode($phone, $code)
    {
        // 审核环境 测试环境不验证      审核账号
        if (config("envname") == 'dev' || config("envname") == 'audit' || in_array($phone, NOT_AUTH)) {
            return;
        }
        $real_code = self::getRealCode($phone);
        if (empty($real_code)) {
            throw new MessageException('验证码已经失效', 200);
        }
        if (empty($code)) {
            throw new MessageException('验证码不能为空', 200);
        }
        if ($real_code != $code) {
            throw new MessageException('验证码错误', 200);
        }
    }

    // 获取缓存中真实的验证码
    public static function getRealCode($phone)
    {
        $instance = MemcacheClient::getInstance();
        return $instance->get(self::$check_prex . $phone);
    }

}